import { ref } from 'vue'
import { ElButton, ElMessage, ElMessageBox } from 'element-plus'
import { get } from 'lodash-es'
import { FileUtils } from '@sat/shared-utils'
import type {
  ElUpload,
  UploadFile,
  UploadFiles,
  UploadRawFile,
  UploadUserFile,
} from 'element-plus'

// 主要的参数，未列出的可参考element-plus官网进行配置
export interface UploadProps {
  // 请求URL
  action: string
  // 设置上传的请求头部
  headers?: {
    Authorization: string
    [x: string]: any
  }
  accept?: string
  limit?: number
  autoUpload?: boolean
  disabled?: boolean
  [x: string]: any
}

export interface ConfigOptions {
  responseMapping?: {
    // 对应关系
    url?: string[] | string
    code?: string[] | string
    name?: string[] | string
    message?: string[] | string
  }
  // 上传接口成功的code值，默认值 0
  successCode?: string | number
  // 上传限制最大字节
  maxSizeByte?: number
  getUploadRef?: () => Promise<Ref<InstanceType<typeof ElUpload>>>
}
/**
 * @description 仅限单文件上传
 */
export function useUpload(props: UploadProps, config: ConfigOptions) {
  const refValue = ref<string>('')
  const refResponse = ref<any>()
  const refFileList = ref<any[]>([])
  const refOriginFileName = ref<string>('')
  const refOriginFileSize = ref<number>()
  return {
    refOriginFileName,
    refOriginFileSize,
    refValue,
    refResponse,
    refFileList,
    uploadProps: {
      slots: {
        trigger: () => {
          return <ElButton type="primary"> 点击上传 </ElButton>
        },
      },
      ...props,
      // 内部强制重写
      withCredentials: true,
      multiple: false,
      drag: false,
      onExceed: (files: File[], uploadFiles: UploadUserFile[]) => {
        ElMessage.warning('文件超出最大个数限制')
      },
      beforeUpload: (file: UploadRawFile) => {
        const suffix = FileUtils.getSuffix(file.name)
        if (!props.accept?.includes(suffix)) {
          ElMessage.warning(`文件格式不正确，请上传${props.accept}格式的文件`)
          return false
        }
        if (file.size && config.maxSizeByte && file.size > config.maxSizeByte) {
          const gb = config.maxSizeByte / 1024 / 1024 / 1024
          const mb = config.maxSizeByte / 1024 / 1024
          const kb = config.maxSizeByte / 1024
          let tip = `${gb}Gb`
          if (gb < 1)
            tip = `${mb}Mb`

          if (mb < 1)
            tip = `${kb}kb`

          ElMessage.warning(
            `您上传的文件已超出上传最大限制：${tip}，请重新选择文件`,
          )
          return false
        }
        refOriginFileName.value = file.name.replaceAll(suffix, '')
        refOriginFileSize.value = file.size
      },
      onPreview: (file: UploadFile) => {
        if (!file.raw && !file.url) {
          return
        }
        ElMessageBox.confirm('想要查看需下载该文件, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning',
        }).then(() => {
          if (file.raw) {
            FileUtils.downloadFile(file.raw)
            return
          }
          const url = file.url
          window.open(url)
        })
      },
      onRemove: (file: UploadFile, fileList: UploadFiles) => {
        refValue.value = ''
        refOriginFileName.value = ''
        refOriginFileSize.value = 0
        refResponse.value = null
      },
      onSuccess: (response: any, file: UploadFile, fileList: UploadFiles) => {
        refResponse.value = response
        if (
          get(response, config.responseMapping?.code ?? 'code')
          === (config.successCode ?? 0)
        ) {
          refValue.value = get(response, config.responseMapping?.url ?? 'url')
          refFileList.value = [
            {
              raw: file.raw,
              name:
                get(response, config.responseMapping?.name ?? 'name') || file.name,
              url: get(response, config.responseMapping?.url ?? 'url'),
            },
          ]
        }
        else {
          ElMessage.error(
            get(response, config.responseMapping?.message ?? 'message') ?? '上传失败',
          )
          fileList.splice(0, 1)
        }
      },
      onError: (
        error: Error,
        uploadFile: UploadFile,
        uploadFiles: UploadFiles,
      ) => {
        ElMessage.error(error.message ?? '上传失败')
        if (config.getUploadRef) {
          config.getUploadRef().then((uploadRef) => {
            uploadRef.value?.clearFiles()
          })
        }
      },
    },
  }
}
